home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
sozobon2.zoo
/
top
/
peep1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-14
|
5KB
|
239 lines
/* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*/
/*
* Single-instruction peephole optimizations and the overall driver routine.
*/
#include "top.h"
void
peep(bp)
register BLOCK *bp;
{
bool peep1(), peep2(), peep3();
extern BLOCK *fhead;
register bool changed;
peep1(bp);
/*
* Loop until no more changes are made. After each change, do
* live/dead analysis or the data gets old. In each loop, make
* at most one change.
*/
do {
changed = peep3(bp);
if (!changed)
changed = peep2(bp);
if (!changed)
changed = peep1(bp);
rhealth(fhead, FALSE);
} while (changed);
}
/*
* ipeep1(ip) - check for changes to the instruction 'ip'
*/
static bool
ipeep1(bp, ip)
register BLOCK *bp;
register INST *ip;
{
/*
* clr.l Dn => moveq.l Dn
*/
if (ip->opcode == CLR && ip->src.amode == REG &&
ISD(ip->src.areg) && (ip->flags & LENL)) {
ip->opcode = MOVEQ;
ip->dst = ip->src; /* we'll have two operands now */
ip->src.amode = IMM;
ip->src.disp = 0;
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* move.* #n,Dn => moveq.l #n,Dn
*
* moveq is always a long operation, but as long as the immediate
* value is appropriate, we don't care what the original length
* was. Clearing upper bytes won't matter.
*/
if (ip->opcode == MOVE && ip->src.amode == IMM && ISD(ip->dst.areg) &&
D8OK(ip->src.disp)) {
ip->opcode = MOVEQ;
ip->flags = LENL;
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* add.x #n, X => addq.x #n, X
*
* where 1 <= n <= 8
*/
if (ip->opcode == ADD && ip->src.amode == IMM &&
ip->src.disp >= 1 && ip->src.disp <= 8) {
ip->opcode = ADDQ;
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* sub.x #n, X => subq.x #n, X
*
* where 1 <= n <= 8
*/
if (ip->opcode == SUB && ip->src.amode == IMM &&
ip->src.disp >= 1 && ip->src.disp <= 8) {
ip->opcode = SUBQ;
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* movem.x Reg,-(sp) => move.x Reg,-(sp)
*/
if (ip->opcode == MOVEM && ip->src.amode == REG &&
ip->dst.areg == SP && ip->dst.amode == (REGI|DEC)) {
ip->opcode = MOVE;
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* movem.x (sp)+,Reg => move.x (sp)+,Reg
*/
if (ip->opcode == MOVEM && ip->dst.amode == REG &&
ip->src.amode == (REGI|INC) && ip->src.areg == SP) {
ip->opcode = MOVE;
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* add[q] #?, Rn
*
* Remove instruction if Rn is dead. This is most often used
* to eliminate the fixup of SP following a function call when
* we're just about to return, since the "unlk" clobbers SP
* anyway.
*/
if ((ip->opcode == ADDQ || ip->opcode == ADD) && ip->src.amode == IMM &&
ip->dst.amode == REG) {
if ((ip->live & RM(ip->dst.areg)) == 0) {
delinst(bp, ip);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
/*
* move.x X, X
*
* Delete as long as X isn't INC or DEC
*/
if ((ip->opcode == MOVE) && opeq(&ip->src, &ip->dst) &&
((ip->src.amode & (INC|DEC)) == 0)) {
delinst(bp, ip);
DBG(printf("%d ", __LINE__))
return TRUE;
}
/*
* move.x Rm, Rn
*
* Delete if Rn is dead.
*/
if (ip->opcode == MOVE &&
ip->src.amode == REG && ip->dst.amode == REG) {
if ((ip->live & RM(ip->dst.areg)) == 0) {
delinst(bp, ip);
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
/*
* cmp.x #0, X => tst.x X
* beq/bne beq/bne
*
* Where X is not An
*/
if (bp->last == ip && (bp->bcode == BEQ || bp->bcode == BNE) &&
ip->opcode == CMP &&
((ip->dst.amode != REG) || !ISA(ip->dst.areg))) {
if (ip->src.amode == IMM && ip->src.disp == 0) {
ip->opcode = TST;
ip->src = ip->dst;
ip->dst.amode = NONE;
DBG(printf("%d ", __LINE__))
return TRUE;
}
}
/*
* add.x #n, Am => lea n(Am), Am
*
* where 'n' is a valid displacement
*/
if (ip->opcode == ADD && ip->src.amode == IMM && ip->dst.amode == REG &&
ISA(ip->dst.areg) && DOK(ip->src.disp)) {
ip->opcode = LEA;
ip->flags = 0;
ip->src.amode = REGID;
ip->src.areg = ip->dst.areg;
DBG(printf("%d ", __LINE__))
return TRUE;
}
return FALSE;
}
/*
* peep1(bp) - peephole optimizations with a window size of 1
*/
static bool
peep1(bp)
register BLOCK *bp;
{
register INST *ip;
register bool changed = FALSE;
register bool bchange;
DBG(printf("p1: "))
for (; bp != NULL ;bp = bp->next) {
bchange = FALSE;
for (ip = bp->first; ip != NULL ;ip = ip->next) {
if (ipeep1(bp, ip)) {
s_peep1++;
changed = TRUE;
bchange = TRUE;
}
}
if (bchange)
bprep(bp);
}
DBG(printf("\n"); fflush(stdout))
return changed;
}